﻿namespace JunionRobotTaskManager.Utility
{
    public class RetryTool
    {
        static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        static int sleepMillisecondsTimeout = 800;

        /// <summary>
        /// 发生Exception重试
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="handler"></param>
        /// <param name="retryTimes">预设重试3次 return default(T)</param>
        /// <returns></returns>
        public static T Retry<T>(Func<T> handler, int retryTimes = 3,int sleepTime=800)
        {
            if (retryTimes <= 0)
            {
                return default(T);
            }

            try
            {
                return handler();
            }
            catch (Exception e)
            {
                retryTimes--;
                logger.Error($"剩余重试次数: {retryTimes}, retry error: {e.Message}");
                System.Threading.Thread.Sleep(sleepTime);
                return Retry(handler, retryTimes);
            }
        }

        /// <summary>
        /// 传入多个动作,遇到Exception 依序执行
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="handlers"></param>
        /// <returns></returns>
        public static T Retry<T>(params Func<T>[] handlers)
        {
            for (int i = 0; i < handlers.Length; i++)
            {
                var handler = handlers[i];
                try
                {
                    return handler();
                }
                catch (Exception e)
                {
                    logger.Error($"第 {i}次执行错误(start from 0): retry error: {e.Message}");
                    System.Threading.Thread.Sleep(sleepMillisecondsTimeout);
                }
            }
            return default(T);
        }

        /// <summary>
        /// 如果发送错误执行重试
        /// </summary>
        /// <param name="handler"></param>
        /// <param name="retryTimes"预设3次</param>
        public static void Retry(Action handler, int retryTimes = 3)
        {
            if (retryTimes <= 0)
            {
                return;
            }

            try
            {
                handler();
            }
            catch (Exception e)
            {
                retryTimes--;
                logger.Error($"剩余重试次数: {retryTimes}, retry error: {e.Message}");
                System.Threading.Thread.Sleep(sleepMillisecondsTimeout);
                Retry(handler, retryTimes);
            }
        }


        /// <summary>
        /// 发生Exception重试
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="handler"></param>
        /// <param name="retryTimes">预设重试3次 return default(T)</param>
        /// <returns></returns>
        public static bool Retry(Func<bool> handler, int retryTimes = 3)
        {
            if (retryTimes <= 0)
            {
                return false;
            }

            try
            {
                if (!handler())
                    throw new Exception($"{nameof(handler)}执行错误");
                else
                    return true;
            }
            catch (Exception e)
            {
                retryTimes--;
                logger.Error($"{nameof(handler)} 执行错误, 剩余重试次数: {retryTimes}, retry error: {e.Message}");
                System.Threading.Thread.Sleep(sleepMillisecondsTimeout);
                return Retry(handler, retryTimes);
            }
        }

    }
}
